﻿using UnityEngine;
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

public abstract class Fleet : IBuildable, IRepeatable, ISerializable
{
	public enum ShipClass
	{
		Dispatchable = 0,
		ColonyShip = 1,
		Frigate = 2,
		Destroyer = 3,
		Cruiser = 4,
		Battleship = 5,
		Titan = 6,
		DoomStar = 7
	}

	private bool m_Repeat = false;

	private ulong m_FleetID;					// fleet serial number
	private string m_DisplayName;
	private double m_BuildCost;
	private double m_OwnCost;
	private GameEnums.TechName[] m_MotherTech;
	private GameEnums.Facilities[] m_MotherFacility;

	private int m_SortRank;						// ranking sorting

	private string m_ShipName;
	private Kingdom m_Belong;					// belong to which kingdom
	private Point3D m_Location;				// current location of fleet
	private ShipClass m_FleetClass;
	private StarSystem m_Dest;				// moving destination
	private StarSystem m_Home;				// docking port
	private bool m_Launched;					// ship is in travel

	private int m_Turn;								// turns left to destination

	#region IBuildable
	public string DisplayName
	{
		get { return m_DisplayName; }
		set { m_DisplayName = value; }
	}

	public double BuildCost
	{
		get { return m_BuildCost; }
		set { m_BuildCost = value; }
	}

	public double OwnCost
	{
		get { return m_OwnCost; }
		set { m_OwnCost = value; }
	}
	#endregion

	#region IRepeatable
	public bool Repeat
	{
		get { return m_Repeat; }
		set { m_Repeat = value; }
	}
	#endregion


	// getters and setters
	#region getters and setters
	public ulong FleetID
	{
		get { return m_FleetID; }
		set { m_FleetID = value; }
	}

	public GameEnums.TechName[] MotherTech
	{
		get { return m_MotherTech; }
		set { m_MotherTech = value; }
	}

	public GameEnums.Facilities[] MotherFacility
	{
		get { return m_MotherFacility; }
		set { m_MotherFacility = value; }
	}

	public int SortRank
	{
		get { return m_SortRank; }
		set { m_SortRank = value; }
	}

	public string ShipName
	{
		get { return m_ShipName; }
		set { m_ShipName = value; }
	}

	public Kingdom Belong
	{
		get { return m_Belong; }
		set { m_Belong = value; }
	}

	public Point3D Location
	{
		get { return m_Location; }
		set { m_Location = value; }
	}

	public ShipClass FleetClass
	{
		get { return m_FleetClass; }
		set { m_FleetClass = value; }
	}

	public StarSystem Dest
	{
		get { return m_Dest; }
		set { m_Dest = value; }
	}

	public StarSystem Home
	{
		get { return m_Home; }
		set { m_Home = value; }
	}

	public bool Launched
	{
		get { return m_Launched; }
		set { m_Launched = value; }
	}

	public int Turn
	{
		get { return m_Turn; }
		set { m_Turn = value; }
	}
	#endregion

	// ISerializable
	ulong ISerializable.Serial
	{
		get { return (ulong)m_FleetID; }
	}


	// constructors
	public Fleet()
	{
		m_FleetID = 0;
		m_BuildCost = 200;
		m_OwnCost = 0.0;

		m_Launched = false;
		m_Turn = -1;

		m_MotherTech = new GameEnums.TechName[] { };
		m_MotherFacility = new GameEnums.Facilities[] { };
	}

	// for IRepeatable
	public bool CheckRepeat()
	{

		return true;
	}

	public bool CheckRepeat(Planet pl)
	{


		return this.CheckRepeat();
	}


	// sub-classes of class Fleet
	public class SolarFleet
	{
		public StarSystem pSolar;
		public int pDistance;
		public int pTurn;
		public List<SelectFleet>[] pDocks = new List<SelectFleet>[3]
		{
			new List<SelectFleet>(), new List<SelectFleet>(), new List<SelectFleet>()
		};

		public SolarFleet(StarSystem star)
		{
			pSolar = star;
		}

		public bool Add(SelectFleet ship, int index)
		{
			if (index < 0 || index > 2)
				return false;

			foreach (SelectFleet sf in pDocks[index])
				if (sf.pShip.FleetID == ship.pShip.FleetID)
					return false;

			pDocks[index].Add(ship);
			pDocks[index].Sort(new SelFleetSorter());

			return true;
		}

	}

	public class LocSorter : IComparer<SolarFleet>
	{
		public int Compare(SolarFleet x, SolarFleet y)
		{
			return Compare(x.pDistance, y.pDistance);
		}

		public int Compare(int x, int y)
		{
			return x - y;						// in reverse order
		}
	}

	public class SelectFleet
	{
		public Fleet pShip;
		public bool pSelected;

		public SelectFleet(Fleet ship)
		{
			pShip = ship;
			pSelected = false;
		}
	}

	public class SelFleetSorter : IComparer<SelectFleet>
	{
		public int Compare(SelectFleet x, SelectFleet y)
		{
			return Compare(x.pShip.SortRank, y.pShip.SortRank);
		}

		public int Compare(int x, int y)
		{
			return x - y;
		}
	}

	public class SortRankSorter : IComparer<Fleet>
	{
		public int Compare(Fleet x, Fleet y)
		{
			return Compare(x.SortRank, y.SortRank);
		}

		public int Compare(int x, int y)
		{
			return x - y;
		}
	}

	// ISerializable
	public virtual void Serialize(GenericWriter writer)
	{
		writer.Write((int)0); // version

		writer.Write((bool)m_Repeat);
		writer.Write((ulong)m_FleetID);
		writer.Write((string)m_DisplayName);
		writer.Write((double)m_BuildCost);
		writer.Write((double)m_OwnCost);

		writer.Write((int)m_MotherTech.Length);

		if (m_MotherTech.Length > 0)
		{
			foreach (GameEnums.TechName tn in m_MotherTech)
				writer.Write((int)tn);
		}

		writer.Write((int)m_MotherFacility.Length);

		if (m_MotherFacility.Length > 0)
		{
			foreach (GameEnums.Facilities ft in m_MotherFacility)
				writer.Write((int)ft);
		}

		writer.Write((int)m_SortRank);
		writer.Write((string)m_ShipName);
		writer.Write((Kingdom)m_Belong);
		writer.Write((Point3D)m_Location);
		writer.Write((int)m_FleetClass);

		writer.Write((StarSystem)m_Dest);
		writer.Write((StarSystem)m_Home);

		writer.Write((bool)m_Launched);
		writer.Write((int)m_Turn);
	}

	public virtual void Deserialize(GenericReader reader)
	{
		int version = reader.ReadInt();

		m_Repeat = reader.ReadBool();
		m_FleetID = reader.ReadULong();
		m_DisplayName = reader.ReadString();
		m_BuildCost = reader.ReadDouble();
		m_OwnCost = reader.ReadDouble();

		int length = reader.ReadInt();
		if (length > 0)
			for (int i = 0; i < length; i++)
				m_MotherTech[i] = (GameEnums.TechName)reader.ReadInt();

		length = reader.ReadInt();

		if (length > 0)
			for (int j = 0; j < length; j++)
				m_MotherFacility[j] = (GameEnums.Facilities)reader.ReadInt();

		m_SortRank = reader.ReadInt();
		m_ShipName = reader.ReadString();
		m_Belong = reader.ReadKingdom();
		m_Location = reader.ReadPoint3D();
		m_FleetClass = (ShipClass)reader.ReadInt();

		m_Dest = reader.ReadStarSystem();
		m_Home = reader.ReadStarSystem();

		m_Launched = reader.ReadBool();
		m_Turn = reader.ReadInt();
	}


	// class methods

}